Make it possible to call gdk_pixbuf_loader_set_size (loader, 0, 0) by
authorMatthias Clasen <maclas@gmx.de>
Wed, 7 Jan 2004 00:26:58 +0000 (00:26 +0000)
committerMatthias Clasen <matthiasc@src.gnome.org>
Wed, 7 Jan 2004 00:26:58 +0000 (00:26 +0000)
Wed Jan  7 01:17:36 2004  Matthias Clasen  <maclas@gmx.de>

* gdk-pixbuf-loader.c (gdk_pixbuf_loader_size_func):
* gdk-pixbuf-loader.c (gdk_pixbuf_loader_set_size):
* gdk-pixbuf-loader.c (gdk_pixbuf_loader_init): Make it possible
to call gdk_pixbuf_loader_set_size (loader, 0, 0) by changing
the initial values of priv->width/height to -1.

* io-tiff.c (tiff_image_parse):
* io-ras.c (RAS2State):
* io-pnm.c (gdk_pixbuf__pnm_image_load_increment):
* io-pcx.c (gdk_pixbuf__pcx_load_increment):
* io-jpeg.c (gdk_pixbuf__jpeg_image_load_increment):
* io-png.c (png_info_callback):
* io-ico.c (DecodeHeader):
* io-bmp.c (DecodeHeader): Call size_func once the size is known,
even if the module can't make use of the scaling information. If
size_func returns 0, don't allocate a pixbuf and return, if
necessary with an error.

* gdk-pixbuf.h:
* gdk-pixbuf-io.c (gdk_pixbuf_get_file_info): A new function
to determine the type and size of an image file without loading
it completely.  (#53725)

16 files changed:
docs/reference/ChangeLog
docs/reference/gdk-pixbuf/gdk-pixbuf-sections.txt
docs/reference/gdk-pixbuf/tmpl/module_interface.sgml
gdk-pixbuf/ChangeLog
gdk-pixbuf/gdk-pixbuf-io.c
gdk-pixbuf/gdk-pixbuf-loader.c
gdk-pixbuf/gdk-pixbuf.h
gdk-pixbuf/io-bmp.c
gdk-pixbuf/io-ico.c
gdk-pixbuf/io-jpeg.c
gdk-pixbuf/io-pcx.c
gdk-pixbuf/io-png.c
gdk-pixbuf/io-pnm.c
gdk-pixbuf/io-ras.c
gdk-pixbuf/io-tga.c
gdk-pixbuf/io-tiff.c

index a3370019d4ce515789c11dabbb9ea0e2b48568ad..05645598d6f7f3d6285fda45266df9c3e4b5cff7 100644 (file)
@@ -1,3 +1,12 @@
+Wed Jan  7 01:27:23 2004  Matthias Clasen  <maclas@gmx.de>
+
+       * gdk-pixbuf/tmpl/module_interface.sgml: Document expected
+       module behaviour if the size_func returns 0.
+
+Wed Jan  7 01:26:07 2004  Matthias Clasen  <maclas@gmx.de>
+
+       * gdk-pixbuf/gdk-pixbuf-sections.txt: Add gdk_pixbuf_get_file_info.
+
 Mon Dec 29 01:40:20 2003  Matthias Clasen  <maclas@gmx.de>
 
        * gtk/gtk-sections.txt: Add gtk_accel_map_{un,}lock_path.
index dc30b4c517e8fbaaf2b666f54b3c0c4d52808d8d..9f625c9fe1b2d95b9fe65d98f7510f3962053ee1 100644 (file)
@@ -57,6 +57,7 @@ GdkPixbufDestroyNotify
 <FILE>file-loading</FILE>
 gdk_pixbuf_new_from_file
 gdk_pixbuf_new_from_file_at_size
+gdk_pixbuf_get_file_info
 </SECTION>
 
 <SECTION>
index c3c86af9696cd30a053982873f833c4b8b9a216b..c6e56b89dd5ee8ee2b2b9f74def14d479b05aea1 100644 (file)
@@ -220,6 +220,12 @@ way to achieve the desired scaling during the loading of the image, it may
 either ignore the size request, or only approximate it -- &gdk-pixbuf; will
 then perform the required scaling on the completely loaded image. 
 </para>
+<para>
+If the function sets @width or @height to zero, the module should interpret
+this as a hint that it will be closed soon and shouldn't allocate further 
+resources. This convention is used to implement gdk_pixbuf_get_file_info()
+efficiently.
+</para>
 
 @width: pointer to a location containing the current image width
 @height: pointer to a location containing the current image height
index f11a942d3c27746b544b2f268c544e8e5ee72099..796b17833cba143badb2783b6d91bd43d1e6f56e 100644 (file)
@@ -1,3 +1,28 @@
+Wed Jan  7 01:17:36 2004  Matthias Clasen  <maclas@gmx.de>
+
+       * gdk-pixbuf-loader.c (gdk_pixbuf_loader_size_func): 
+       * gdk-pixbuf-loader.c (gdk_pixbuf_loader_set_size): 
+       * gdk-pixbuf-loader.c (gdk_pixbuf_loader_init): Make it possible
+       to call gdk_pixbuf_loader_set_size (loader, 0, 0) by changing
+       the initial values of priv->width/height to -1.
+       
+       * io-tiff.c (tiff_image_parse): 
+       * io-ras.c (RAS2State): 
+       * io-pnm.c (gdk_pixbuf__pnm_image_load_increment): 
+       * io-pcx.c (gdk_pixbuf__pcx_load_increment): 
+       * io-jpeg.c (gdk_pixbuf__jpeg_image_load_increment): 
+       * io-png.c (png_info_callback): 
+       * io-ico.c (DecodeHeader): 
+       * io-bmp.c (DecodeHeader): Call size_func once the size is known,
+       even if the module can't make use of the scaling information. If
+       size_func returns 0, don't allocate a pixbuf and return, if 
+       necessary with an error.
+
+       * gdk-pixbuf.h: 
+       * gdk-pixbuf-io.c (gdk_pixbuf_get_file_info): A new function 
+       to determine the type and size of an image file without loading
+       it completely.  (#53725)
+
 Sun Jan  4 00:44:57 2004  Matthias Clasen  <maclas@gmx.de>
 
        * gdk-pixbuf.c (gdk_pixbuf_class_init): Turn the pixbuf 
index dc96b44d28217c2dd13aa6f547d2ccdaefcb9fd9..dc5dc51431f422cc38cb46e659dd6cd948e95845 100644 (file)
@@ -910,6 +910,93 @@ gdk_pixbuf_new_from_file_at_size (const char *filename,
        return pixbuf;
 }
 
+static void
+info_cb (GdkPixbufLoader *loader, 
+        int              width,
+        int              height,
+        gpointer         data)
+{
+       struct {
+               GdkPixbufFormat *format;
+               int width;
+               int height;
+       } *info = data;
+
+       g_return_if_fail (width > 0 && height > 0);
+
+       info->format = gdk_pixbuf_loader_get_format (loader);
+       info->width = width;
+       info->height = height;
+
+       gdk_pixbuf_loader_set_size (loader, 0, 0);
+}
+
+/**
+ * gdk_pixbuf_get_file_info:
+ * @filename: The name of the file to identify.
+ * @width: Return location for the width of the image, or %NULL
+ * @height: Return location for the height of the image, or %NULL
+ * 
+ * Parses an image file far enough to determine its format and size.
+ * 
+ * Returns: A #GdkPixbufFormat describing the image format of the file 
+ *    or %NULL if the image format wasn't recognized. The return value 
+ *    is owned by GdkPixbuf and should not be freed.
+ *
+ * Since: 2.4
+ **/
+GdkPixbufFormat *
+gdk_pixbuf_get_file_info (const gchar  *filename,
+                         gint         *width, 
+                         gint         *height)
+{
+       GdkPixbufLoader *loader;
+       GError *temp = NULL;
+       guchar buffer [4096];
+       int length;
+       FILE *f;
+       struct {
+               GdkPixbufFormat *format;
+               gint width;
+               gint height;
+       } info;
+
+       g_return_val_if_fail (filename != NULL, NULL);
+
+       f = fopen (filename, "rb");
+       if (!f)
+               return NULL;
+
+       loader = gdk_pixbuf_loader_new ();
+
+       info.format = NULL;
+       info.width = -1;
+       info.height = -1;
+               
+       g_signal_connect (loader, "size-prepared", G_CALLBACK (info_cb), &info);
+
+       while (!feof (f)) {
+               length = fread (buffer, 1, sizeof (buffer), f);
+               if (length > 0) {
+                       if (!gdk_pixbuf_loader_write (loader, buffer, length, NULL))
+                               break;
+               }
+               if (info.format != NULL)
+                       break;
+       }
+
+       fclose (f);
+       gdk_pixbuf_loader_close (loader, NULL);
+       g_object_unref (G_OBJECT (loader));
+
+       if (width) 
+               *width = info.width;
+       if (height) 
+               *height = info.height;
+
+       return info.format;
+}
+
 /**
  * gdk_pixbuf_new_from_xpm_data:
  * @data: Pointer to inline XPM data.
index b4c135252e532410357ff4cf6b7eba3db1abf115..d980eea97bb88a6248d3bfd6428f70b3311c3af7 100644 (file)
@@ -208,6 +208,9 @@ gdk_pixbuf_loader_init (GdkPixbufLoader *loader)
         GdkPixbufLoaderPrivate *priv;
   
         priv = g_new0 (GdkPixbufLoaderPrivate, 1);
+        priv->width = -1;
+        priv->height = -1;
+
         loader->priv = priv;
 }
 
@@ -253,7 +256,7 @@ gdk_pixbuf_loader_set_size (GdkPixbufLoader *loader,
                            gint             height)
 {
         GdkPixbufLoaderPrivate *priv = GDK_PIXBUF_LOADER (loader)->priv;
-        g_return_if_fail (width > 0 && height > 0);
+        g_return_if_fail (width >= 0 && height >= 0);
 
         if (!priv->size_fixed) 
                 {
@@ -268,7 +271,7 @@ gdk_pixbuf_loader_size_func (gint *width, gint *height, gpointer loader)
         GdkPixbufLoaderPrivate *priv = GDK_PIXBUF_LOADER (loader)->priv;
 
         /* allow calling gdk_pixbuf_loader_set_size() before the signal */
-        if (priv->width == 0 && priv->height == 0
+        if (priv->width == -1 && priv->height == -1
                 {
                         priv->width = *width;
                         priv->height = *height;
index 0f5728f33627cc95bf32264e606a827b55cd38b6..234f88310e26f78349457541d2214b83f67d2a4c 100644 (file)
@@ -302,6 +302,10 @@ gchar    **gdk_pixbuf_format_get_mime_types  (GdkPixbufFormat *format);
 gchar    **gdk_pixbuf_format_get_extensions  (GdkPixbufFormat *format);
 gboolean   gdk_pixbuf_format_is_writable     (GdkPixbufFormat *format);
 
+GdkPixbufFormat *gdk_pixbuf_get_file_info (const gchar  *filename,
+                                          gint         *width, 
+                                          gint         *height);
+
 G_END_DECLS
 
 #include <gdk-pixbuf/gdk-pixbuf-loader.h>
index f7f50df15e912d01b9f6c0b4b8aa3d2edd9d0998..8212834e1b94222aa9290cd7e29473b30793e860 100644 (file)
@@ -144,6 +144,7 @@ struct bmp_compression_state {
 /* Progressive loading */
 
 struct bmp_progressive_state {
+       GdkPixbufModuleSizeFunc size_func;
        GdkPixbufModulePreparedFunc prepared_func;
        GdkPixbufModuleUpdatedFunc updated_func;
        gpointer user_data;
@@ -319,41 +320,52 @@ static gboolean DecodeHeader(unsigned char *BFH, unsigned char *BIH,
                State->LineWidth = (State->LineWidth / 4) * 4 + 4;
 
        if (State->pixbuf == NULL) {
+               if (State->size_func) {
+                       gint width = State->Header.width;
+                       gint height = State->Header.height;
+
+                       (*State->size_func) (&width, &height, State->user_data);
+                       if (width == 0 || height == 0) {
+                               State->read_state = READ_STATE_DONE;
+                               State->BufferSize = 0;
+                               return TRUE;
+                       }
+               }
+
                if (State->Type == 32 || 
                    State->Compressed == BI_RLE4 || 
                    State->Compressed == BI_RLE8)
                        State->pixbuf =
-                           gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8,
-                                          (gint) State->Header.width,
-                                          (gint) State->Header.height);
+                               gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8,
+                                              (gint) State->Header.width,
+                                              (gint) State->Header.height);
                else
                        State->pixbuf =
-                           gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8,
-                                          (gint) State->Header.width,
-                                          (gint) State->Header.height);
-
-                if (State->pixbuf == NULL) {
-                        g_set_error (error,
-                                     GDK_PIXBUF_ERROR,
-                                     GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
-                                     _("Not enough memory to load bitmap image"));
+                               gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8,
+                                              (gint) State->Header.width,
+                                              (gint) State->Header.height);
+               
+               if (State->pixbuf == NULL) {
+                       g_set_error (error,
+                                    GDK_PIXBUF_ERROR,
+                                    GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
+                                    _("Not enough memory to load bitmap image"));
                        State->read_state = READ_STATE_ERROR;
-                        return FALSE;
-                }
-
+                       return FALSE;
+                       }
+               
                if (State->prepared_func != NULL)
                        /* Notify the client that we are ready to go */
                        (*State->prepared_func) (State->pixbuf, NULL, State->user_data);
-
+               
+               /* make all pixels initially transparent */
+               if (State->Compressed == BI_RLE4 || State->Compressed == BI_RLE8) {
+                       memset (State->pixbuf->pixels, 0, State->pixbuf->rowstride * State->Header.height);
+                       State->compr.p = State->pixbuf->pixels 
+                               + State->pixbuf->rowstride * (State->Header.height- 1);
+               }
        }
        
-       /* make all pixels initially transparent */
-       if (State->Compressed == BI_RLE4 || State->Compressed == BI_RLE8) {
-               memset (State->pixbuf->pixels, 0, State->pixbuf->rowstride * State->Header.height);
-               State->compr.p = State->pixbuf->pixels 
-                       + State->pixbuf->rowstride * (State->Header.height- 1);
-       }
-
        State->BufferDone = 0;
        if (State->Type <= 8) {
                State->read_state = READ_STATE_PALETTE;
@@ -485,6 +497,7 @@ gdk_pixbuf__bmp_image_begin_load(GdkPixbufModuleSizeFunc size_func,
        struct bmp_progressive_state *context;
 
        context = g_new0(struct bmp_progressive_state, 1);
+       context->size_func = size_func;
        context->prepared_func = prepared_func;
        context->updated_func = updated_func;
        context->user_data = user_data;
@@ -1036,6 +1049,9 @@ gdk_pixbuf__bmp_image_load_increment(gpointer data,
                                return FALSE;
 
                        break;
+               case READ_STATE_DONE:
+                       return TRUE;
+                       break;
 
                default:
                        g_assert_not_reached ();
index 482cff29a99a59d931adc14c4135b8cff7294d6d..e19f86f8f7096214704da07fa791de5c8edb4d2f 100644 (file)
@@ -126,6 +126,7 @@ struct headerpair {
 };
 
 struct ico_progressive_state {
+       GdkPixbufModuleSizeFunc size_func;
        GdkPixbufModulePreparedFunc prepared_func;
        GdkPixbufModuleUpdatedFunc updated_func;
        gpointer user_data;
@@ -400,6 +401,19 @@ static void DecodeHeader(guchar *Data, gint Bytes,
 
 
        if (State->pixbuf == NULL) {
+#if 1
+               if (State->size_func) {
+                       gint width = State->Header.width;
+                       gint height = State->Header.height;
+
+                       (*State->size_func) (&width, &height, State->user_data);
+                       if (width == 0 || height == 0) {
+                               State->LineWidth = 0;
+                               return;
+                       }
+               }
+#endif
+
                State->pixbuf =
                    gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8,
                                   State->Header.width,
@@ -445,6 +459,7 @@ gdk_pixbuf__ico_image_begin_load(GdkPixbufModuleSizeFunc size_func,
        struct ico_progressive_state *context;
 
        context = g_new0(struct ico_progressive_state, 1);
+       context->size_func = size_func;
        context->prepared_func = prepared_func;
        context->updated_func = updated_func;
        context->user_data = user_data;
@@ -828,6 +843,9 @@ gdk_pixbuf__ico_image_load_increment(gpointer data,
                        GError *decode_err = NULL;
                        DecodeHeader(context->HeaderBuf,
                                     context->HeaderDone, context, &decode_err);
+                       if (context->LineBuf != NULL && context->LineWidth == 0)
+                               return TRUE;
+
                        if (decode_err) {
                                g_propagate_error (error, decode_err);
                                return FALSE;
index 191372890b20696b811846fdbd7db190acf66ba0..85d75dfe60be264603b8b90e73ebbe8a1f700e48 100644 (file)
@@ -650,7 +650,12 @@ gdk_pixbuf__jpeg_image_load_increment (gpointer data,
                        
                        width = cinfo->image_width;
                        height = cinfo->image_height;
-                       (* context->size_func) (&width, &height, context->user_data);
+                       if (context->size_func) {
+                               (* context->size_func) (&width, &height, context->user_data);
+                               if (width == 0 || height == 0)
+                                       return FALSE;
+                       }
+                       
                        for (cinfo->scale_denom = 2; cinfo->scale_denom <= 8; cinfo->scale_denom *= 2) {
                                jpeg_calc_output_dimensions (cinfo);
                                if (cinfo->output_width < width || cinfo->output_height < height) {
index 5ccbeea5a841ec45928d39c698c33ca9e8851197..4a9d0bef810ee9bd2e55168b6c905d0578564aa5 100644 (file)
@@ -606,8 +606,12 @@ gdk_pixbuf__pcx_load_increment(gpointer data, const guchar *buf, guint size,
                                g_set_error(error, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_CORRUPT_IMAGE, _("Image has invalid width and/or height"));
                                return FALSE;
                        }
-                       if(context->size_func)
-                               context->size_func(&width, &height, context->user_data);
+                       if (context->size_func)
+                         {
+                           (*context->size_func) (&width, &height, context->user_data);
+                           if (width == 0 || height == 0)
+                             return TRUE;
+                         }
 
                        switch(context->bpp) {
                                default:
index 5ddca7510836aa1b5dad842af4a0a8a24827d89e..fa35734a7679d1b8c26a75acd70de494ef2fc721 100644 (file)
@@ -358,6 +358,7 @@ struct _LoadContext {
         png_structp png_read_ptr;
         png_infop   png_info_ptr;
 
+        GdkPixbufModuleSizeFunc size_func;
         GdkPixbufModulePreparedFunc prepare_func;
         GdkPixbufModuleUpdatedFunc update_func;
         gpointer notify_user_data;
@@ -398,6 +399,7 @@ gdk_pixbuf__png_image_begin_load (GdkPixbufModuleSizeFunc size_func,
         
         lc->fatal_error_occurred = FALSE;
 
+        lc->size_func = size_func;
         lc->prepare_func = prepare_func;
         lc->update_func = update_func;
         lc->notify_user_data = user_data;
@@ -593,7 +595,18 @@ png_info_callback   (png_structp png_read_ptr,
         if (color_type & PNG_COLOR_MASK_ALPHA)
                 have_alpha = TRUE;
         
-        lc->pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, have_alpha, 8, width, height);
+        if (lc->size_func) {
+                gint w = width;
+                gint h = height;
+                (* lc->size_func) (&w, &h, lc->notify_user_data);
+                
+                if (w == 0 || h == 0) {
+                        lc->fatal_error_occurred = TRUE;
+                        return;
+                }
+        }
+
+        lc->pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, have_alpha, 8, width, height);
 
         if (lc->pixbuf == NULL) {
                 /* Failed to allocate memory */
index 1fc1fe7c08ad4ebb57749adb15cd3b7f3090780b..437ccaf0e0547da325122cfcba7fa70b3916c83f 100644 (file)
@@ -55,6 +55,7 @@ typedef struct {
 typedef struct {
        GdkPixbufModuleUpdatedFunc updated_func;
        GdkPixbufModulePreparedFunc prepared_func;
+       GdkPixbufModuleSizeFunc size_func;
        gpointer user_data;
        
        GdkPixbuf *pixbuf;
@@ -820,6 +821,7 @@ gdk_pixbuf__pnm_image_begin_load (GdkPixbufModuleSizeFunc size_func,
                return NULL;
        }
        memset (context, 0, sizeof (PnmLoaderContext));
+       context->size_func = size_func;
        context->prepared_func = prepared_func;
        context->updated_func  = updated_func;
        context->user_data = user_data;
@@ -944,6 +946,16 @@ gdk_pixbuf__pnm_image_load_increment (gpointer data,
                        
                        context->got_header = TRUE;
                }
+
+               if (context->size_func) {
+                       gint w = context->width;
+                       gint h = context->height;
+                       (*context->size_func) (&w, &h, context->user_data);
+                       
+                       if (w == 0 || h == 0) 
+                               return FALSE;
+               }
+               
                
                /* scan until we hit image data */
                if (!context->did_prescan) {
index fba4b9900f1ac227457ff756ebef52a3df58812c..40ba370d53d094598a4fa683b00518bf9e6d49df 100644 (file)
@@ -68,6 +68,7 @@ struct rasterfile {
 /* Progressive loading */
 
 struct ras_progressive_state {
+       GdkPixbufModuleSizeFunc size_func;
        GdkPixbufModulePreparedFunc prepared_func;
        GdkPixbufModuleUpdatedFunc updated_func;
        gpointer user_data;
@@ -174,6 +175,15 @@ static gboolean RAS2State(struct rasterfile *RAS,
 
 
        if (!State->pixbuf) {
+               if (State->size_func) {
+                       gint width = State->Header.width;
+                       gint height = State->Header.height;
+                       
+                       (*State->size_func) (&width, &height, State->user_data);
+                       if (width == 0 || height == 0)
+                               return FALSE;
+               }
+
                if (State->RasType == 32)
                        State->pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8,
                                                        (gint) State->Header.width,
@@ -227,6 +237,7 @@ gdk_pixbuf__ras_image_begin_load(GdkPixbufModuleSizeFunc size_func,
        struct ras_progressive_state *context;
 
        context = g_new0(struct ras_progressive_state, 1);
+       context->size_func = size_func;
        context->prepared_func = prepared_func;
        context->updated_func = updated_func;
        context->user_data = user_data;
index 1486d44803d7b638db75ba053edff1497b96b7fb..32c6af0b579caf9a6bbd8b181ba7e6f29d063700 100644 (file)
@@ -137,6 +137,7 @@ struct _TGAContext {
        gboolean prepared;
        gboolean done;
 
+       GdkPixbufModuleSizeFunc sfunc;
        GdkPixbufModulePreparedFunc pfunc;
        GdkPixbufModuleUpdatedFunc ufunc;
        gpointer udata;
@@ -334,6 +335,16 @@ static gboolean fill_in_context(TGAContext *ctx, GError **err)
        w = LE16(ctx->hdr->width);
        h = LE16(ctx->hdr->height);
 
+       if (ctx->sfunc) {
+               gint wi = w;
+               gint hi = h;
+               
+               (*ctx->sfunc) (&wi, &hi, ctx->udata);
+               
+               if (wi == 0 || hi == 0) 
+                       return FALSE;
+       }
+
        ctx->pbuf = get_contiguous_pixbuf (w, h, alpha);
 
        if (!ctx->pbuf) {
@@ -872,6 +883,7 @@ static gpointer gdk_pixbuf__tga_begin_load(GdkPixbufModuleSizeFunc f0,
        ctx->prepared = FALSE;
        ctx->done = FALSE;
 
+       ctx->sfunc = f0;
        ctx->pfunc = f1;
        ctx->ufunc = f2;
        ctx->udata = udata;
index 3e6d9fca0598c8da1e6eada2129bc796b13e5e5d..2d47f6594406da09affaee936c5ed89514281061 100644 (file)
@@ -47,6 +47,7 @@
 typedef struct _TiffContext TiffContext;
 struct _TiffContext
 {
+       GdkPixbufModuleSizeFunc size_func;
        GdkPixbufModulePreparedFunc prepare_func;
        GdkPixbufModuleUpdatedFunc update_func;
        gpointer user_data;
@@ -225,6 +226,15 @@ tiff_image_parse (TIFF *tiff, TiffContext *context, GError **error)
                 return NULL;                
         }
 
+       if (context && context->size_func) {
+                gint w = width;
+                gint h = height;
+               (* context->size_func) (&w, &h, context->user_data);
+                
+                if (w == 0 || h == 0)
+                    return NULL;
+        }
+
         pixels = g_try_malloc (bytes);
 
         if (!pixels) {
@@ -370,6 +380,7 @@ gdk_pixbuf__tiff_image_begin_load (GdkPixbufModuleSizeFunc size_func,
        TiffContext *context;
         
        context = g_new0 (TiffContext, 1);
+       context->size_func = size_func;
        context->prepare_func = prepare_func;
        context->update_func = update_func;
        context->user_data = user_data;